%%% File    : flash_server.erl
%%% Author  :  <whhbest>
%%% Description : 
%%% Created : 14 Mar 2011 by  <>

-module(flash_server).

-behaviour(gen_server).

-export([start_link/1]).

-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
	terminate/2, code_change/3]).

-export([acceptor/2, start_pool/1]).

-define(Size, 10).

-define(Port, 843).

-define(Server, ?MODULE).

-record(state, {sup,
	       asock,
	       pool}).

%%--------
start_link(Sup) ->
    gen_server:start_link({local, ?Server}, ?MODULE, [Sup], []).


%%------callbacks
init([Sup]) ->
    process_flag(trap_exit, true),
    Opts = [binary,
	   {packet, 0},
	   {reuseaddr, true},
	   {backlog, 100},
	   {active, false},
	   {nodelay, true}],
    {Tag, Asock} = gen_tcp:listen(?Port, Opts),
    case Tag of
	error ->
	    exit(Asock);
	ok ->
	    Fun = fun(_, List) ->
			  Pid = spawn_link(?MODULE, acceptor, [self(), Asock]),
			  [Pid|List]
		  end,
	    Pool = start_pool(Fun),
	    {ok, #state{sup=Sup,
		       asock=Asock,
		       pool=Pool}}
    end.

handle_call(_Req, _From, S) ->
    {reply, ok, S}.

handle_cast({acceptor, Pid}, S=#state{asock=Asock, pool=Pool}) ->
    Npid = spawn_link(?MODULE, acceptor, [self(), Asock]),
    {noreply, S#state{pool=[Npid|lists:delete(Pid, Pool)]}};

handle_cast(_Msg, S) ->
    {noreply, S}.

handle_info({'EXIT', Pid, Reason}, 
	    S=#state{asock=Asock, pool=Pool}) when Reason =/= normal ->
    case lists:member(Pid, Pool) of
	true ->
	    Npid = spawn_link(?MODULE, acceptor, [self(), Asock]),
	    {noreply, S#state{pool=[Npid|lists:delete(Pid, Pool)]}};
	false ->
	    {noreply, S}
    end;
	    
handle_info(_Info, S) ->
    {noreply, S}.

terminate(_Reason, _S) ->
    ok.

code_change(_Oldvsn, S, _Extra) ->
    {ok, S}.

%%--------internal

start_pool(Fun) ->
    lists:foldl(Fun, [], lists:seq(1, ?Size)).

acceptor(Parent, Asock) ->    
    {Tag, Sock} = gen_tcp:accept(Asock),
    gen_server:cast(Parent, {acceptor, self()}),
    case Tag of
	error ->
	    exit(normal);
	ok ->
	    loop(Sock),
	    ok
    end.

loop(Sock) ->
    case gen_tcp:recv(Sock, 0) of
	{ok, _Bin} ->
	    gen_tcp:send(Sock, "<?xml version=\"1.0\"?>
                <cross-domain-policy>
                <allow-access-from domain=\"*\" to-ports=\"*\"/>  
                </cross-domain-policy>\0"),
	    gen_tcp:close(Sock),
	    ok;
	{error, closed} ->
	    ok
    end.
    
